﻿namespace OOP
{
    using System;
    using System.Collections.Generic;

    public class GSM
    {
        private const byte MinModelAndManufacturerLength = 2;
        private const byte MaxModelAndManufacturerLength = 10;

        private static readonly GSM IPhone4S = new GSM("4S", "Apple", 1350, "Steve Jobs", new Display(4.7f, "65K"), new Battery("BatteryModel-13.37", 550, 250, Battery.BatteryType.LiPo2400));
        
        private string model;
        private string manufacturer;
        private decimal? price;
        private string owner;
        private Display display;
        private Battery battery;
        private List<Call> callHistory = new List<Call>();

        public GSM()
        {
        }

        public GSM(string model, string manufacturer, Display display, Battery battery)
        {
            this.Model = model;
            this.Manufacturer = manufacturer;
            this.Display = display;
            this.Battery = battery;
        }

        public GSM(string model, string manufacturer, decimal price, string owner, Display display, Battery battery) : this(model, manufacturer, display, battery)
        {
            this.Price = price;
            this.Owner = owner;
        }

        public static GSM IPhone4SSpecifications
        {
            get
            {
                return IPhone4S;
            }
        }

        public string Model
        {
            get
            {
                return this.model;
            }

            private set
            {
                if (value.Length < MinModelAndManufacturerLength || value.Length > MaxModelAndManufacturerLength)
                {
                    throw new ArgumentOutOfRangeException("Incorrect gsm model.");
                }
                else if (this.model != null) // ensures that the field will be readonly
                {
                    throw new ArgumentException("The gsm model has been already set.");
                }
                else
                {
                    this.model = value;
                }
            }
        }

        public string Manufacturer
        {
            get
            {
                return this.manufacturer;
            }

            private set
            {
                if (value.Length < MinModelAndManufacturerLength || value.Length > MaxModelAndManufacturerLength)
                {
                    throw new ArgumentOutOfRangeException("Incorrect gsm manufacturer.");
                }
                else if (this.manufacturer != null) // ensures that the field will be readonly
                {
                    throw new ArgumentException("The gsm manufacturer has been already set.");
                }
                else
                {
                    this.manufacturer = value;
                }
            }
        }

        public decimal? Price
        {
            get
            {
                return this.price;
            }

            private set
            {
                if (value <= 0)
                {
                    throw new ArgumentOutOfRangeException("The prices cannot be zero or negative value.");
                }
                else
                {
                    this.price = value;
                }
            }
        }

        public string Owner
        {
            get
            {
                return this.owner;
            }

            private set
            {
                this.owner = value;
            }
        }

        public Display Display
        {
            get
            {
                return this.display;
            }

            private set
            {
                if (value == null)
                {
                    throw new ArgumentException("The display is virtual (null).");
                }
                else
                {
                    this.display = value;
                }
            }
        }

        public Battery Battery
        {
            get
            {
                return this.battery;
            }

            private set
            {
                if (value == null)
                {
                    throw new ArgumentException("The battery is virtual (null).");
                }
                else
                {
                    this.battery = value;
                }
            }
        }

        public List<Call> CallHistory
        {
            get
            {
                return this.callHistory;
            }
        }

        public void AddCall(Call callForAdd)
        {
            this.callHistory.Add(callForAdd);
        }

        public void RemoveCall(int indexOfCall)
        {
            this.callHistory.RemoveAt(indexOfCall);
        }

        public void ClearCallHistory()
        {
            this.callHistory.Clear();
        }

        public decimal TotalPrice(float pricePerMin)
        {
            int totalSecondsCalls = 0;
            
            foreach (var call in this.callHistory)
            {
                totalSecondsCalls += call.Duration;
            }

            return (decimal)(pricePerMin * ((totalSecondsCalls / 60) + 1));
        }

        public void PrintGSMInfo()
        {
            Console.WriteLine(this.manufacturer);
            Console.WriteLine(this.model);
            Console.WriteLine(this.price);
            Console.WriteLine(this.owner);
            Console.WriteLine(this.display);
            Console.WriteLine(this.battery);
        }

        public override string ToString()
        {
            return this.Model + Environment.NewLine + this.manufacturer + Environment.NewLine + this.price + Environment.NewLine + this.owner + Environment.NewLine + this.display + Environment.NewLine + this.battery;
        }
    }
}